/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.jm.mala.lazyModel;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.comparators.ComparatorChain;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

/**
 *
 * @author joao
 * @param <T>
 */
public class GenericLazyDataModelLocal<T extends Serializable> extends LazyDataModel<T> {

    private static final long serialVersionUID = -2620652404901813658L;

    private final List<T> datasource;

    public GenericLazyDataModelLocal(List<T> datasource) {
        this.datasource = datasource;
    }

    @Override
    public T getRowData(String rowKey) {
        for (T entidade : datasource) {
            if (entidade.getClass().equals(rowKey)) {
                return entidade;
            }
        }

        return null;
    }

    @Override
    public Object getRowKey(T m) {
        return m.getClass();
    }

    @Override
    public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
        List<T> data = new ArrayList<>();

        //filter
        for (T entidade : datasource) {
            boolean match = true;

            if (filters != null) {
                for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
                    try {
                        String filterProperty = it.next();
                        String filterValue = removerAcentos(filters.get(filterProperty).toString().toLowerCase());
                        Field field = entidade.getClass().getDeclaredField(filterProperty);
                        field.setAccessible(true);
                        String value = removerAcentos(field.get(entidade).toString().toLowerCase());

                        if (value.contains(filterValue)) {
                            match = true;
                        } else {
                            match = false;
                            break;
                        }
                    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
                        match = false;
                    }
                }
            }

            if (match) {
                data.add(entidade);
            }
        }

        //sort
        if (sortField != null) {
            boolean lSorter = SortOrder.ASCENDING.equals(sortOrder);
            List sortFields = new ArrayList();
            sortFields.add(new BeanComparator(sortField));
            ComparatorChain multiSort = new ComparatorChain(sortFields);
            if (lSorter) {
                java.util.Collections.sort(data, multiSort);
            } else {
                java.util.Collections.sort(data, multiSort.reversed());
            }

        }

        //rowCount
        int dataSize = data.size();
        this.setRowCount(dataSize);

        //paginate
        if (dataSize > pageSize) {
            try {
                return data.subList(first, first + pageSize);
            } catch (IndexOutOfBoundsException e) {
                return data.subList(first, first + (dataSize % pageSize));
            }
        } else {
            return data;
        }
    }

    public static String removerAcentos(String stringAcentuada) {
        if (stringAcentuada == null) {
            return null;
        }
        return Normalizer.normalize(stringAcentuada, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");
    }
}
